/*
 * DefaultDropTargetListener.java
 *
 * Created on March 4, 2005, 9:26 PM
 */

package fr.umlv.dnd;

import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.runtime.FolderImpl;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;

import fr.umlv.authentication.SessionHandler;
import fr.umlv.cmis.listview.ViewComponent;
import fr.umlv.model.ClientModel;
import fr.umlv.utils.ExceptionUtils;

// TODO: Auto-generated Javadoc
/**
 * The listener interface for receiving customDropTarget events.
 * The class that is interested in processing a customDropTarget
 * event implements this interface, and the object created
 * with that class is registered with a component using the
 * component's <code>addCustomDropTargetListener<code> method. When
 * the customDropTarget event occurs, that object's appropriate
 * method is invoked.
 *
 * @see CustomDropTargetEvent
 */
public class CustomDropTargetListener implements DropTargetListener, PropertyChangeListener {
	
	/** The target. */
	protected JComponent target;
	
	/** The can import. */
	protected boolean canImport;
	
	/** The last position. */
	protected Point lastPosition;

	/** The drop target. */
	protected DropTarget dropTarget;
	
	/** The view. */
	protected JComponent view;
	
	/**
	 * Instantiates a new custom drop target listener.
	 */
	public CustomDropTargetListener() {
		throw new IllegalStateException("Component in parameters needed !");
	}

	/**
	 * Instantiates a new custom drop target listener.
	 *
	 * @param leftView the left view
	 */
	public CustomDropTargetListener(JComponent leftView) {
		this.view = leftView;
		leftView.addPropertyChangeListener(this);
		dropTarget = new DropTarget(leftView,
				DnDConstants.ACTION_COPY_OR_MOVE, 
				this, 
				leftView.isEnabled(), null);
	}

	/**
	 * Save component state.
	 *
	 * @param c the c
	 */
	protected void saveComponentState(JComponent c) {
	}

	/* (non-Javadoc)
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent evt) {
	}
	
	/**
	 * Restore component state.
	 *
	 * @param c the c
	 */
	protected void restoreComponentState(JComponent c) {
	}

	/**
	 * Restore component state for drop.
	 *
	 * @param c the c
	 */
	protected void restoreComponentStateForDrop(JComponent c) {
	}

	/**
	 * Update insertion location.
	 *
	 * @param c the c
	 * @param p the p
	 */
	protected void updateInsertionLocation(JComponent c, Point p) {

	}

	/* (non-Javadoc)
	 * @see java.awt.dnd.DropTargetListener#dragEnter(java.awt.dnd.DropTargetDragEvent)
	 */
	public void dragEnter(DropTargetDragEvent evt) {
		target =(JComponent)evt.getDropTargetContext().getComponent();
		TransferHandler th = target.getTransferHandler();
		if (th != null) {
			canImport = th.canImport(target, evt.getCurrentDataFlavors());
		}
		if (canImport) {
			saveComponentState(target);
			lastPosition = evt.getLocation();
		}
	}

	/* (non-Javadoc)
	 * @see java.awt.dnd.DropTargetListener#dragOver(java.awt.dnd.DropTargetDragEvent)
	 */
	public void dragOver(DropTargetDragEvent evt) {
		if (canImport) {
			Point p = evt.getLocation();
			updateInsertionLocation(target, p);
			lastPosition = p;
		}
	}


	/* (non-Javadoc)
	 * @see java.awt.dnd.DropTargetListener#dragExit(java.awt.dnd.DropTargetEvent)
	 */
	public void dragExit(DropTargetEvent evt) {
		if (canImport) {
			restoreComponentState(target);
		}

		target =(JComponent)evt.getDropTargetContext().getComponent();
	}

	/* (non-Javadoc)
	 * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent)
	 */
	@SuppressWarnings("unchecked")
	public void drop(DropTargetDropEvent evt) {
		if (evt.getSourceActions() == DnDConstants.ACTION_COPY_OR_MOVE) {
			evt.rejectDrop();
			return;
		}
		evt.acceptDrop(DnDConstants.ACTION_MOVE);
		if (evt.isDataFlavorSupported(CmisObjectTransferable.CMIS_DATA_FLAVOR)) {
			Transferable transferable = evt.getTransferable();
			for (DataFlavor df:transferable.getTransferDataFlavors()) {
				if (df.equals(CmisObjectTransferable.CMIS_DATA_FLAVOR)) {
					List<CmisObject> src;
					try {
						src = (List<CmisObject>)transferable.getTransferData(df);
						moveCmisObject(src);
					} catch (UnsupportedFlavorException e) {
						ExceptionUtils.createJXErrorException(e, null);
					} catch (IOException e) {
						ExceptionUtils.createJXErrorIOException(e, null);
					}
				}
			}

		} else if (evt.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
			Transferable transferable = evt.getTransferable();
			ViewComponent viewComp = (ViewComponent) view ;
			CmisObject cmisObject = viewComp.getViewModel().getCurrentDirectory();
			Folder folder = (FolderImpl) cmisObject;
			for (DataFlavor df:transferable.getTransferDataFlavors()) {
				if (df.isFlavorJavaFileListType()) {
					List<File> list;
					try {
						list = (List<File>)transferable.getTransferData(df);
						copyFiles(list, folder);
					} catch (CmisRuntimeException cmisre) {
						ErrorInfo info = new ErrorInfo(cmisre.getMessage(), cmisre.getMessage(), cmisre.getErrorContent(), "CmisRuntimeException", cmisre, Level.SEVERE, null);
        		        JXErrorPane.showDialog(view, info);
					} catch (ClassCastException e) {
						ErrorInfo info = new ErrorInfo(e.getMessage(), e.getMessage(), e.getMessage(), "content", e, Level.SEVERE, null);
        		        JXErrorPane.showDialog(view, info);
					} catch (UnsupportedFlavorException e) {
						ErrorInfo info = new ErrorInfo(e.getMessage(), e.getMessage(), e.getMessage(), "content", e, Level.SEVERE, null);
        		        JXErrorPane.showDialog(view, info);
					} catch (IOException e) {
						ErrorInfo info = new ErrorInfo(e.getMessage(), e.getMessage(), e.getMessage(), "content", e, Level.SEVERE, null);
        		        JXErrorPane.showDialog(view, info);
					}
				}
			}
		}

		evt.dropComplete(true);
		if (canImport) {
			restoreComponentStateForDrop(target);
		}
	}


	/* (non-Javadoc)
	 * @see java.awt.dnd.DropTargetListener#dropActionChanged(java.awt.dnd.DropTargetDragEvent)
	 */
	public void dropActionChanged(DropTargetDragEvent dtde) {
	}

	/**
	 * Move cmis object.
	 *
	 * @param src the src
	 */
	private void moveCmisObject(List<CmisObject> src) {
	}

	/**
	 * Copy files.
	 *
	 * @param list the list
	 * @param folder the folder
	 */
	private void copyFiles(List<File> list, Folder folder) {
		ViewComponent viewComp = (ViewComponent) view ;
		ClientModel cmisClientModel = viewComp.getViewModel().getModel();

		try {
			if(SessionHandler.getEnableWizard())
				cmisClientModel.createDocumentsWithProgressBarAndWizard(view, viewComp.getViewModel(),"cmis:document,P:cm:titled,P:cm:author,P:cm:generalclassifiable", list, folder, VersioningState.NONE);
			else
				cmisClientModel.createDocumentsWithProgressBar(view, viewComp.getViewModel(),"cmis:document,P:cm:titled,P:cm:author,P:cm:generalclassifiable", list, folder, VersioningState.NONE);
		} catch (CmisInvalidArgumentException e) {
			System.err.println(e.getErrorContent());
			System.err.println(e.getMessage());
			System.err.println(e.getLocalizedMessage());
		} catch (CmisRuntimeException cmisre) {
			cmisre.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
